﻿// Copyright (c) 2007-2021 西安交通信息投资营运有限公司 版权所有
// 作者:吕艳阳

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using XCI.Helper;
using XCI.Service;

namespace XCI.Core
{
    /// <summary>
    /// 服务器文件操作
    /// </summary>
    public class ServerFile
    {
        /// <summary>
        /// 本地文件目录
        /// </summary>
        public string LocalCatalog { get; private set; }

        /// <summary>
        /// 本地文件路径
        /// </summary>
        public string LocalFilePath { get; private set; }

        /// <summary>
        /// 服务器文件目录
        /// </summary>
        public string ServerCatalog { get; private set; }

        /// <summary>
        /// 服务器文件路径
        /// </summary>
        public string ServerFilePath { get; private set; }

        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get; private set; }

        /// <summary>
        /// 不包含扩展名的文件名
        /// </summary>
        public string FileNameWithoutExtension => !string.IsNullOrEmpty(FileName) ? Path.GetFileNameWithoutExtension(FileName) : string.Empty;

        /// <summary>
        /// 初始化服务器文件操作实例
        /// </summary>
        /// <param name="localCatalog">本地文件目录</param>
        /// <param name="serverCatalog">服务器文件目录</param>
        /// <param name="fileName">文件名</param>
        public ServerFile(string localCatalog, string serverCatalog, string fileName)
        {
            if (string.IsNullOrEmpty(fileName)) throw new ArgumentNullException(nameof(fileName));
            if (string.IsNullOrEmpty(localCatalog)) throw new ArgumentNullException(nameof(localCatalog));

            FileName = fileName;
            LocalCatalog = IOHelper.FixLocalCatalog(localCatalog);
            LocalFilePath = Path.Combine(LocalCatalog, fileName);
            ServerCatalog = IOHelper.FixServerCatalog(serverCatalog);
            ServerFilePath = $"{ServerCatalog}/{fileName}";
        }

        /// <summary>
        /// 根据本地文件路径创建
        /// </summary>
        /// <param name="localFilePath">本地文件路径</param>
        /// <param name="serverCatalog">服务器文件目录</param>
        public static ServerFile CreateByLocalFile(string localFilePath, string serverCatalog)
        {
            if (string.IsNullOrEmpty(localFilePath)) throw new ArgumentNullException(nameof(localFilePath));
            if (string.IsNullOrEmpty(serverCatalog)) throw new ArgumentNullException(nameof(serverCatalog));

            var fileInfo = new FileInfo(localFilePath);
            return new ServerFile(fileInfo.DirectoryName, serverCatalog, fileInfo.Name);
        }

        /// <summary>
        /// 根据服务器文件路径创建
        /// </summary>
        /// <param name="serverFilePath">服务器文件路径</param>
        /// <param name="localCatalog">本地目录,如果为null,则取程序所在目录</param>
        public static ServerFile CreateByServerFile(string serverFilePath, string localCatalog = null)
        {
            if (string.IsNullOrEmpty(serverFilePath)) throw new ArgumentNullException(nameof(serverFilePath));
            serverFilePath = serverFilePath.Replace("\\", "/");
            var serverCatalogIndex = serverFilePath.LastIndexOf("/", StringComparison.Ordinal);
            var serverCatalog = string.Empty;
            if (serverCatalogIndex > -1)
            {
                serverCatalog = serverFilePath.Substring(0, serverCatalogIndex);
            }

            var tempFilePath = serverFilePath.Replace("/", "\\");
            if (tempFilePath.Substring(0, 1) == "\\")
            {
                tempFilePath = tempFilePath.Substring(1);
            }

            if (string.IsNullOrEmpty(localCatalog))
            {
                localCatalog = AppDomain.CurrentDomain.BaseDirectory;
            }
            var localFilePath = Path.Combine(localCatalog, tempFilePath);
            var fileInfo = new FileInfo(localFilePath);

            return new ServerFile(fileInfo.DirectoryName, serverCatalog, fileInfo.Name);
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        public async Task<FileModel> UploadAsync()
        {
            if (!File.Exists(LocalFilePath)) return null;
            return await DataFileUploadService.Instance.UploadAsync(LocalFilePath, ServerFilePath);
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="md5File">是否计算文件md5并发送到服务端</param>
        public async Task DownloadAsync(bool md5File = true)
        {
            string md5 = string.Empty;
            if (md5File)
            {
                md5 = StringHelper.Md5File(LocalFilePath);
            }

            try
            {
                await DataFileUploadService.Instance.DownloadAsync(ServerFilePath, LocalFilePath, md5);
            }
            catch
            {
                // ignored
            }
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        public async Task DeleteAsync()
        {
            await DataFileUploadService.Instance.DeleteAsync(ServerFilePath);
            IOHelper.DeleteFile(LocalFilePath);
        }

        /// <summary>
        /// 复制文件
        /// </summary>
        /// <param name="destFileName">目标文件名</param>
        public Task CopyAsync(string destFileName)
        {
            var destServerFilePath = $"{ServerCatalog}/{destFileName}{Path.GetExtension(FileName)}";
            return DataFileUploadService.Instance.CopyAsync(ServerFilePath, destServerFilePath);
        }

        /// <summary>
        /// 文件在服务器中是否存在
        /// </summary>
        public Task<bool> ExistsAsync()
        {
            return DataFileUploadService.Instance.ExistsAsync(ServerFilePath);
        }

        /// <summary>
        /// 查询文件服务器所在目录文件列表
        /// </summary>
        public Task<List<FileModel>> ListAsync()
        {
            return DataFileUploadService.Instance.ListAsync(ServerCatalog);
        }
    }
}